<?php
/*
    OpenLib
    Copyright (C) 2011  Michael Gukov, Pham Thi Thuy Duong

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


namespace Sun\Html\Collections;

class LinkedList
{
    private $first;
    private $last;
    private $count;

    protected function FirstInsert(LinkedListNode $node)
    {
        if ($this->count === 0)
        {
            $this->first = $this->last = $node;
            $this->count = 1;
            return true;
        }
        return false;
    }

    public function __construct()
    {
        $this->first = $this->last = null;
        $this->count = 0;
    }

    public function Get($key)
    {
        $cur = $this->first;
        while (isset($cur))
        {
            if ($cur->key == $key) return $cur;
            $cur = $cur->next;
        }
        return null;
    }
    public function AddLast(LinkedListNode $node)
    {
        if (!$this->FirstInsert($node))
        {
            $this->last->next = $node;
            $node->prev = $this->last;
            $this->last = $node;
            ++$this->count;
        }
    }
    public function AddFirst(LinkedListNode $node)
    {
        if (!$this->FirstInsert($node))
        {
            $this->first->prev = $node;
            $node->next = $this->first;
            $this->first = $node;
            ++$this->count;
        }
    }
    public function InsertAfter(LinkedListNode $node, $after)
    {
        $n1 = $this->Get($after);
        if ($n1 === null)
            throw new Exception ("Element with key = {$after} not found");

        if ($n1->key == $this->last->key)
            $this->AddLast($node);
        else
        {
            $n2 = $n1->next;
            $n2->prev = $node;
            $n1->next = $node;
            $node->next = $n2;
            $node->prev = $n1;
            ++$this->count;
        }
    }
    public function First()
    {
        return $this->first;
    }
    public function Last()
    {
        return $this->last;
    }
    public function RemoveFirst()
    {
        $this->first->next->prev = null;
        $this->first = $this->first->next;
        --$this->count;

    }
    public function RemoveLast()
    {
        $this->last->prev->next = null;
        $this->last = $this->last->prev;
        --$this->count;
    }
    public function Remove($key)
    {
        $node = $this->Get($key);
        if ($node === null)
            throw new Exception ("Element with key = {$key} not found");

        if ($node->key == $this->first->key)
        {
            $this->RemoveFirst();
        }
        else if ($node->key == $this->last->key)
        {
            $this->RemoveLast();
        }
        else
        {
            $node->next->prev = $node->prev;
            $node->prev->next = $node->next;
            --$this->count;
        }
    }
    public function ToArray()
    {
        $arr = array();
        $cur = $this->first;
        while (isset($cur))
        {
            $arr[$cur->key] = $cur->value;
            $cur = $cur->next;
        }
        return $arr;
    }
    public function Count()
    {
        return $this->count;
    }
}

interface ISession
{
    function Serialize();
    function Restore();
}